﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows;

namespace HlELock.Core
{
    public static class UsbHidHelper
    {
        public const uint GENERIC_READ = 0x80000000;//winapi函数CreateFile相关参数
        public const uint GENERIC_WRITE = 0x40000000;
        public const uint FILE_SHARE_READ = 0x00000001;
        public const uint FILE_SHARE_WRITE = 0x00000002;
        public const uint OPEN_EXISTING = 3;
        public const uint FILE_FLAG_OVERLAPPED = 0x40000000;
        public const int DBT_DEVICEARRIVAL = 0x8000;  // 检测到新设备
        public const int DBT_DEVICEREMOVEPENDING = 0x8003; // 设备将要移除
        public const int DBT_DEVICEREMOVECOMPLETE = 0x8004;  // 设备已经移除
        public const int DBT_DEVTYP_DEVICEINTERFACE = 0x00000005; // device interface class
        public const int DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000;
        public const int ERROR_NO_MORE_ITEMS = 259;
        public const uint DEVICE_ARRIVAL = 3;	// 设备插入事件,已经插入
        public const uint DEVICE_REMOVE_PEND = 1;	// 设备将要拔出
        public const uint DEVICE_REMOVE = 0;    // 设备拔出事件,已经拔出


        private static void LogError(string message)
        {
            Debug.Write(message);
        }

        public static List<IUsbHid> GetDeviceList()//检测设备
        {
            uint deviceNo = 0;
            byte[] buf = new byte[1024];
            IntPtr hHID = IntPtr.Zero;//设备句柄
            int strlen = 0;

            var result = new List<IUsbHid>();

            winapi.SetLastError(0);
            while (winapi.GetLastError() != ERROR_NO_MORE_ITEMS)
            {
                if (CH9326DLL.CH9326GetDevicePath(deviceNo, buf, Convert.ToUInt32(buf.Length)))
                {
                    //打开设备,并获得设备句柄
                    hHID = winapi.CreateFile(buf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, IntPtr.Zero);
                    if (hHID == new IntPtr(-1))
                    {
                        deviceNo++;
                        continue;
                    }
                    for (int i = 0; i < buf.Length; i++)
                    {
                        if (buf[i] == 0)
                        {
                            strlen = i + 1;//DevicePath路径长度
                            break;
                        }
                    }
                    var uhi = new UsbHid
                    {
                        Path = Encoding.UTF8.GetString(buf, 0, strlen - 1)//得到设备路径
                    };

                    IntPtr dh = CH9326DLL.CH9326OpenDevicePath(uhi.Path);
                    if (dh == new IntPtr(-1))
                    {
                        LogError("连接设备失败");
                        break;
                    }

                    ushort _vid = 0, _pid = 0, _ver = 0;//VID、PID和版本号
                                                        //获取厂商ID和设备ID
                    if (CH9326DLL.CH9326GetAttributes(dh, ref _vid, ref _pid, ref _ver) == 0)
                    {
                        CH9326DLL.CH9326CloseDevice(dh);
                        LogError("获取厂商Id和设备Id信息失败");
                        break;
                    }
                    Array.Clear(buf, 0, buf.Length);

                    if (CH9326DLL.CH9326GetProductString(dh, buf, (uint)buf.Length) == 1)
                    {
                        for (int i = 0; (i < buf.Length); i += 2)
                        {
                            if (buf[i] == 0)
                            {
                                strlen = i; break;
                            }
                        }
                        var productName = Encoding.Unicode.GetString(buf, 0, strlen);
                        uhi.ProductName = productName;
                    }

                    if (CH9326DLL.CH9326GetManufacturerString(dh, buf, (uint)buf.Length) == 1)
                    {
                        for (int i = 0; (i < buf.Length); i += 2)
                        {
                            if (buf[i] == 0)
                            {
                                strlen = i; break;
                            }
                        }
                        var manufacturer = Encoding.Unicode.GetString(buf, 0, strlen);
                        uhi.Manufacturer = manufacturer;
                    }

                    uhi.VID = _vid;
                    uhi.PID = _pid;
                    uhi.VER = _ver;
                    result.Add(uhi);
                    CH9326DLL.CH9326CloseDevice(dh);
                    winapi.CloseHandle(hHID);
                }
                deviceNo++;
            }
            return result;
        }
    }
}
